#include "Operation.h"
#include "Cent.h"
#include "Dollor.h"

#define CHECK_PTR(ptr, result) if(ptr == 0) return result;
#define CHECK_PTR_VOID(ptr) CHECK_PTR(ptr,  )

static WORD16 valueOf(const Usd* usd)
{
	CHECK_PTR(usd, 0);

	return usd->amount * usd->unit.value;
}

BOOL eq(const Usd* lhs, const Usd* rhs)
{
	CHECK_PTR(lhs, FALSE);
	CHECK_PTR(rhs, FALSE);
  	return valueOf(lhs)  == valueOf(rhs);
}

Usd plus(const Usd* lhs, const Usd* rhs)
{
	Usd reuslt = {valueOf(lhs) + valueOf(rhs), Cent};
	return reuslt;
}

Usd minus(const Usd* lhs, const Usd* rhs)
{
	Usd reuslt = {valueOf(lhs) - valueOf(rhs), Cent};
	return reuslt;
}

  
void noramlPrint(const Usd* usd, char* output)
{
	CHECK_PTR_VOID(output);
	CHECK_PTR_VOID(usd);
	usd->unit.print(usd->amount, output);
}

static void goNext(const WORD16 value, WORD16* divider, WORD16* remain)
{
    *divider = *remain / value;
	*remain %= value;
}

void cascadePrint(const Usd* usd, char* output)
{
	 Usd denominations[] =
		{
			{100, Dollar},
			{50,  Dollar},
			{20,  Dollar},
			{10,  Dollar},
			{5,   Dollar},
			{2,   Dollar},
			{1,   Dollar},
			{50,  Cent},
			{25,  Cent},
			{10,  Cent},
			{5,   Cent},
			{1,   Cent},
	
	};
	static WORD16 size = sizeof(denominations)/sizeof(Usd);
	WORD16 divider = 0;
	WORD16 remain = valueOf(usd);

	CHECK_PTR_VOID(output);
	CHECK_PTR_VOID(usd);
	
	for(BYTE i = 0; i< size; ++i)
	{
		goNext(valueOf(&denominations[i]), &divider, &remain);
		if (divider <= 0) continue;
			   
		output += sprintf(output, "%d*", divider);
		output += denominations[i].unit.print(denominations[i].amount, output);
		
		if (remain > 0)
		{
			output += sprintf(output, ", ");
		}
	}
}
